home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d12
/
cc03.arc
/
LS.C
< prev
next >
Wrap
Text File
|
1986-03-14
|
15KB
|
632 lines
/* ls - a Unix-like directory listing program for MS-DOS 2.x
*
* Copyright (c) 1984 R. Edward Nather
*
*/
#include <stdio.h>
#define CIC86
/* customizing constants */
#define QS '\\' /* filename separator character */
#define DQS "\\" /* filename separator (string) */
#define ID 0 /* always identify directory if 1 */
#define ALL 0 /* show hidden files by default if 1 */
#define LONG 0 /* long listing by default if 1 */
#define COLM 0 /* 1-column listing by default if 1 */
#define RSORT 0 /* reverse sort by default if 1 */
#define TSORT 0 /* time sort by default if 1 */
#define DU 0 /* include disk use by default if 1 */
#define NAMESIZ 13 /* 12 character name + NULL */
#define ONECS 512 /* cluster size on one-sided floppy */
#define TWOCS 1024 /* cluster size on two-sided floppy */
#define HARDCS 4096 /* cluster size on hard disk */
#define SCRSIZ 22 /* scrolling size of display screen */
struct dta /* DOS Disk Transfer Address table */
{
char reserved[21]; /* used in "find next" operation */
char attr; /* file attribute byte */
int ftime; /* time of last modification */
int fdate; /* date of last modification */
long fsize; /* file size in bytes */
char fname[NAMESIZ]; /* filename and extension */
};
struct outbuf /* output buffer -- array of file structs */
{
unsigned oattr;
unsigned odate;
unsigned otime;
long osize;
char oname[NAMESIZ+1];
} *obuf;
char spath[80]; /* holds current pathname string */
/* global variables and flags */
int allf = ALL; /* include hidden & system files */
int ll = LONG; /* long listing */
int colm = COLM; /* 1-column format */
int rev = RSORT; /* reverse sort */
int tsrt = TSORT; /* timesort the listing */
int usage = DU; /* print disk usage */
int recd; /* recursive descent requested */
int sizonly; /* only print sizes */
int np; /* number of groups printed */
int nargs; /* number of non-option arguments */
int clsize = 0; /* size of a cluster, in bytes */
int clmask; /* clsize-1 for rounding & chopping */
int drive; /* code number for drive requested */
int tsc; /* 1 if output is to console screen */
long left; /* unused space left on disk */
long total; /* total of sizes encountered */
main(argc, argv)
int argc;
char *argv[];
{
char *s;
int c = 0;
int nt = 0;
/* process input options */
while(--argc > 0 && (*++argv)[0] == '-') {
for(s = argv[0]+1; *s != '\0'; s++) {
switch(tolower(*s)) {
case 'a': /* -a: list all files */
allf = (allf == 0); /* reverse default value */
break;
case 'c': /* -c: 1-column listing requested */
colm = (colm == 0);
break;
case 'l': /* -l: long listing requested */
ll = (ll == 0);
break;
case 'r': /* -r: reverse sort direction */
rev = (rev == 0);
break;
case 's': /* -s: print sizes only */
sizonly = 1;
if(*(s+1) == '1') {
clsize = ONECS; /* diskuse for 1-sided floppy */
s++;
nt++;
}
else if(*(s+1) == '2') {
clsize = TWOCS; /* or 2-sided */
s++;
nt++;
}
break;
case 't': /* -t: time sort requested */
tsrt = (tsrt == 0);
break;
case 'u': /* -u: print disk usage */
usage = (usage == 0);
break;
case 'R': /* -R: recursively list subdirs */
recd = 1;
break;
default:
fprintf(stderr, "unknown arg %c\n", *s);
exit(1);
}
}
}
nargs = argc;
tsc = toscreen(); /* find out if output is to console screen */
obuf = (struct outbuf *)malloc(sizeof(*obuf)); /* point to free memory */
if(argc == 0) {
argc++;
curdrv(spath); /* default to current drive */
}
else
strcpy(spath, *argv);
for(;;) { /* cycle through args present */
if(spath[1] == ':' && spath[2] == '\0') /* if drive only */
getpath(spath); /* get path */
if(usage || sizonly || ll)
c = getsize(spath); /* get use data only if needed */
if(c == 0)
search(spath); /* go do the hard work */
if(--argc > 0)
strcpy(spath, *++argv);
else {
if(usage || sizonly) {
if(np > 1) {
fprintf(stdout, "-------\n%7ld bytes total", total);
if(!nt)
fputs("; ", stdout);
}
if(!nt)
fprintf(stdout, "%7ld bytes left on drive %c\n",
left, drive+'a');
}
return;
}
}
}
getsize(path) /* get file cluster size */
char *path;
{
if(clsize == 0) /* if size not already set */
if((clsize = getcl(path)) == 0) { /* get cluster size for drive */
fprintf(stderr,
"Invalid drive: %c\n", *path);
return(1);
}
clmask = clsize-1;
return(0);
}
/* toscreen - find out if output is to console screen */
toscreen()
{
struct { unsigned int ax, bx, cx, dx, si, di, ds, es;
} r;
r.ax = 0x4400;
r.bx = 1;
sysint(0x21, &r, &r);
return(r.dx & 1);
}
/* search - search 'path' for filename or directory */
search(path)
char *path;
{
struct dta dta; /* DOS file data table */
extern struct outbuf; /* array of file structs */
extern int nargs; /* number of files or directories */
int path_len; /* length of initial path */
int z; /* char counter */
int k = 0; /* counts number of entries found */
char work[80]; /* working path string */
int comp(); /* string, time comparison routine */
int mask = 0x0010; /* attribute mask */
long bytes = 0; /* count of disk usage this directory */
if(allf)
mask = 0x001F;
strcpy(work,path);
path_len = strlen(work); /* save original path length */
if(!find_first(work, &dta, 0) || work[path_len-1] == QS) {
if(work[path_len-1] != QS) {
strcat(work, DQS); /* if path is to a directory */
path_len++;
}
strcat(work,"*.*"); /* list everything in it */
}
if(find_first(work, &dta, mask)) {
do {
if(dta.attr & 0x08) /* ignore volume label */
continue;
if(dta.fname[0] == '.' && !allf) /* unless -a option */
continue; /* ignore "." and ".." */
obuf[k].oattr = dta.attr; /* stash this entry */
obuf[k].otime = dta.ftime;
obuf[k].odate = dta.fdate;
obuf[k].osize = dta.fsize;
strcpy(obuf[k].oname, dta.fname);
if(usage || sizonly) {
if((dta.attr & 0x10) && dta.fname[0] != '.') {
bytes += clsize; /* sum up disk usage */
}
else if(dta.fsize) {
obuf[k].osize = ((dta.fsize + clmask) & (long)(~clmask));
bytes += obuf[k].osize;
}
}
k++;
} while(find_next(&dta));
}
else {
work[path_len-1] = NULL;
fprintf(stderr, "Can't find a file or directory named \"%s\"\n", work);
return;
}
work[path_len] = NULL; /* restore directory pathname */
if(np++ && !sizonly)
fputc(endlin(),stdout); /* separate listing blocks */
if(usage || sizonly) {
total += bytes; /* total bytes to date */
fprintf(stdout, "%7ld ", bytes);
}
if(recd || nargs > 1 || usage || sizonly || ID) {
fprintf(stdout, "%s", work); /* identify the block */
fputc(endlin(),stdout);
}
if(!sizonly) {
qsort(obuf,k,sizeof(obuf[0]),comp); /* sort the entries */
if(ll)
longlist(k); /* and print them */
else
shortlist(k);
}
if(!recd)
return; /* quit if not -R */
strcat(work, "*.*");
if(find_first(work, &dta, mask)) /* else find all sub-dirs */
do {
if(dta.attr & 0x10 && dta.fname[0] != '.') {
work[path_len] = 0; /* discard old name */
for(z=0; dta.fname[z] != NULL; z++)
dta.fname[z] = tolower(dta.fname[z]);
strcat(work, dta.fname); /* install a new one */
strcat(work, DQS);
search(work); /* and recurse */
}
} while(find_next(&dta));
return;
}
/* find_first - find first file in chosen directory */
find_first(path, dta, mask)
char *path;
struct dta *dta;
int mask;
{
struct { int ax, bx, cx;
char *dx;
int si, di, ds, es;
} r;
extern int _showds();
r.ax = 0x1A00; /* DOS interrupt 1A */
r.dx = (char *)dta;
r.ds = _showds();
sysint(0x21, &r, &r); /* sets data transfer address */
r.ax = 0x4E00; /* DOS interrupt 4E */
r.cx = mask;
r.dx = path;
r.ds = _showds();
return(!(sysint(0x21, &r, &r) & 1)); /* fills the structure */
}
/* find_next - find the next file in the same directory */
find_next(dta)
struct dta *dta;
{
struct { int ax, bx, cx;
char *dx;
int si, di, ds, es;
} r;
extern int _showds();
r.ax = 0x1A00;
r.dx = (char *)dta;
r.ds = _showds();
sysint(0x21, &r, &r); /* set dta */
r.ax = 0x4F00;
return(!(sysint(0x21, &r, &r) & 1)); /* fill the table */
}
/* curdrv - get current default drive */
curdrv(sp)
char *sp;
{
struct { int ax, bx, cx;
char *dx, *si, *di, *ds, *es;
} r;
r.ax = 0x1900; /* DOS interrupt 19 */
sysint(0x21, &r, &r); /* gets current drive number */
*sp++ = r.ax + 'a'; /* convert to symbolic drive name */
*sp++ = ':';
return;
}
/* getpath - get path to directory on indicated drive */
getpath(sp)
char *sp;
{
struct { int ax, bx, cx, dx;
char *si;
int di, ds, es;
} r;
extern int _showds();
strcat(sp, DQS); /* append root file symbol to drive name */
r.ax = 0x4700; /* DOS interrupt 47 gets path string */
r.dx = *sp - '`'; /* convert drive name to index */
r.ds = _showds();
r.si = sp + 3; /* paste string after root symbol */
sysint(0x21, &r, &r);
return;
}
/* getcl - get cluster size & space left on requested drive */
getcl(pp)
char *pp;
{
struct { int ax, bx, cx, dx, si, di, ds, es;} r;
int cs;
extern long left;
extern int drive;
if(*(pp+1) == ':') /* use specified drive if any */
r.ax = *pp - 'a';
else {
r.ax = 0x1900; /* else get code for default drive */
sysint(0x21, &r, &r);
}
drive = r.ax & 0x7F;
if(!usage && !sizonly && drive == 2)
return(HARDCS);
else {
r.dx = drive + 1; /* 0 = default, 1 = a, etc */
r.ax = 0x3600;
sysint(0x21, &r, &r); /* DOS interrupt hex 36 */
if(r.ax == 0xFFFF) /* gets free disk space */
return(0); /* and other goodies */
else {
cs = r.ax * r.cx; /* r.ax = sectors/cluster */
left = (long)cs * r.bx; /* r.bx = # unused clusters */
return(cs); /* r.cx = bytes/sector */
} /* r.dx = drive capacity (clusters) */
}
}
/* comp - compare size of two entries */
comp(a,b)
struct outbuf *a, *b;
{
int y;
if(tsrt) {
if(a->odate != b->odate) /* if dates differ */
y = (a->odate < b->odate) ? -1 : 1; /* that settles it */
else
y = (a->otime < b->otime) ? -1 : 1; /* else compare times */
return((rev) ? y : -y);
}
else {
y = strcmp(a->oname, b->oname); /* name comparison */
return((rev) ? -y : y);
}
}
/* shortlist - print a list of names in 5 columns */
shortlist(k)
int k; /* total number to print */
{
int i, m, n;
if(colm)
n = k; /* set for 1-column listing */
else
n = (k + 4)/5; /* or 5-column */
for(i=0; i < n; i++){
for(m = 0; (i+m) < k; m += n) {
if(obuf[i+m].oattr & 0x10)
strcat(obuf[i+m].oname, DQS); /* mark directories */
putname(i+m); /* print the name */
fputs(" ", stdout);
}
fputc(endlin(),stdout);
}
return;
}
/* putname - convert name to lower case and print */
putname(i)
int i;
{
int c, j = 0;
while((c = tolower(obuf[i].oname[j])) != 0) {
fputc(c, stdout);
j++;
}
while(j++ < NAMESIZ - 1) /* pad to columnarize */
fputc(' ', stdout);
}
/* endlin - end a line and watch for screen overflow */
static int lc = 0; /* line counter */
endlin(fp)
FILE *fp;
{
extern int tsc; /* true if output is to screen */
int c;
if(tsc && ++lc >= SCRSIZ) { /* pause if output is to console screen */
fputs("\n\033[7m--More--", fp); /* and we've shown a screenful */
c = ci();
fputs("\033[0m\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b", fp);
switch(c) {
case '\r': /* <RETURN> - show 1 more line */
lc = SCRSIZ - 1;
break;
case 'q': /* quit with "q" or "ctrl-C" */
case '\003':
exit(0);
default:
lc = 0; /* else show another screenful */
break;
}
return('\b');
}
else
return('\n');
}
/* longlist - list everything about files in two columns */
struct llst { /* structure to hold file information */
char *fattr; /* file attribute pointer */
long size; /* file size */
int day; /* the day of creation */
int mnum; /* month number */
int yr;
int hh; /* creation times */
int mm;
int ap; /* am or pm */
} l;
longlist(k)
int k; /* total number to list */
{
int i, m, n, cdate;
char *mon, *mname();
cdate = gcdate(); /* get current date (in months) */
if(colm)
n = k; /* set for 1 column listing */
else
n = (k + 1)/2; /* or for 2 column listing */
for(i=0; i < n; i++){
for(m = 0; (m+i) < k; m += n) {
fill(i+m, &l); /* fill llst structure */
mon = mname(l.mnum); /* conv month # to name */
fprintf(stdout, "%s%7ld %2d %s ",
l.fattr, l.size, l.day, mon);
if(cdate >= (l.yr * 12 +l.mnum) + 12)
fprintf(stdout, " %4d ", l.yr); /* print year if too old */
else {
fprintf(stdout, "%2d:%02d%c ",
l.hh, l.mm, l.ap); /* else print time */
}
putname(i+m);
if(m+n < k)
fputs("\272 ", stdout); /* double bar separator */
}
fputc(endlin(),stdout);
}
return;
}
/* fill - fill long list structure with file information */
fill(i, ll)
int i;
struct llst *ll;
{
int j, k;
static char fbuf[16][4] = {
"--w",
"---",
"-hw",
"-h-",
"s-w",
"s--",
"shw",
"sh-",
"d-w",
"d--",
"dhw",
"dh-",
"d-w",
"d--",
"dhw",
"dh-"
};
if((obuf[i].oattr & 0x10) && obuf[i].oname[0] != '.') {
ll->size = clsize;
j = 8; /* if directory, use block size */
} /* and set dir attr offset */
else {
ll->size = obuf[i].osize; /* else use file size */
j = 0; /* and file attr offset */
}
ll->fattr = fbuf[(obuf[i].oattr & 0x07) + j]; /* point to symbolic attr */
ll->day = obuf[i].odate & 0x1F;
ll->mnum = (obuf[i].odate >> 5) & 0x0F;
ll->yr = (obuf[i].odate >> 9) + 1980;
k = obuf[i].otime >> 5; /* this is a mess */
ll->mm = k & 0x3f;
ll->ap = ((ll->hh = k >> 6) >= 12) ? 'p' : 'a';
if(ll->hh > 12)
ll->hh -= 12;
if(ll->hh == 0)
ll->hh = 12;
return;
}
/* gcdate - get current date (in months) for comparison */
gcdate()
{
struct { unsigned int ax, bx, cx, dx, si, di, ds, es;} r;
r.ax = 0x2A00;
sysint(0x21, &r, &r);
return(r.cx * 12 + (r.dx >> 8)); /* yr * 12 + month */
}
/* mname - convert month number to month name */
char *mname(n)
int n;
{
static char *name[] = {
"???",
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
};
return((n < 1 || n > 12) ? name[0] : name[n]);
}
#ifdef CIC86
_showds()
{
struct{int cs, ss, ds, es;} r;
segread(&r);
return(r.ds);
}
ci()
{
return(bdos(7) & 0xFF);
}
#endif